//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Target Devices:
// Tool versions:
//
// Create Date:    2011-08-18 15:28
// Project Name:
// Description:
//     
// Dependencies:
//
// Revision: 1.0
// Revision 0.01 - File Created
//
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ns
module lcd_gray_buff
(
    input               clk,
    input               rst,

    // line buffer fifo 
    input [31:0]        in_fifo_rddata,
    output reg          in_fifo_rdreq,
    input               in_fifo_empty,
    input               in_fifo_alempty,

    //lcd output fifo
    output [7:0]        out_fifo_data,
    output              out_fifo_empty,
    output              out_fifo_alempty,
    input               out_fifo_rdreq
);

/********************************************************\
Parameter
\********************************************************/
localparam  U_DLY           = 1;

/********************************************************\
Signals
\********************************************************/

reg [7:0]       fifo_wrdata;
reg             fifo_wrreq;
wire            fifo_alfull;
reg             wr_data_valid;
reg             wr_done;
reg [1:0]       wr_data_cnt;

reg [7:0]       in_fifo_data0;
reg [7:0]       in_fifo_data1;
reg [7:0]       in_fifo_data2;
reg [7:0]       in_fifo_data3;

reg             in_fifo_rdreq_dly1;

/********************************************************\
main code
\********************************************************/

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_rdreq <= 1'b0;
    end
    else if(~fifo_alfull & wr_done & (~in_fifo_rdreq))
    begin
        in_fifo_rdreq   <= #U_DLY ~in_fifo_empty;
    end
    else
    begin
        in_fifo_rdreq   <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_rdreq_dly1  <= 1'b0;
    end
    else
    begin
        in_fifo_rdreq_dly1  <= #U_DLY in_fifo_rdreq;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        in_fifo_data0 <= 'h0;
        in_fifo_data1 <= 'h0;
        in_fifo_data2 <= 'h0;
        in_fifo_data3 <= 'h0;
    end
    else if(in_fifo_rdreq_dly1)
    begin
        in_fifo_data0 <= #U_DLY in_fifo_rddata[7:0];
        in_fifo_data1 <= #U_DLY in_fifo_rddata[15:8];
        in_fifo_data2 <= #U_DLY in_fifo_rddata[23:16];
        in_fifo_data3 <= #U_DLY in_fifo_rddata[31:24];
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        fifo_wrreq  <= 1'b0;
    end
    else if(~fifo_wrreq & wr_data_valid)
    begin
        fifo_wrreq  <= #U_DLY ~fifo_alfull;
    end
    else
    begin
        fifo_wrreq  <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_data_cnt <= 'h0;
    end
    else if(fifo_wrreq)
    begin
        wr_data_cnt <= #U_DLY wr_data_cnt + 1'b1;
    end
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_data_valid   <= 1'b0;
    end
    else if(in_fifo_rdreq_dly1)
    begin
        wr_data_valid   <= #U_DLY 1'b1;
    end
    else if(fifo_wrreq & (wr_data_cnt==2'd3))
    begin
        wr_data_valid   <= #U_DLY 1'b0;
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        wr_done <= 1'b1;
    end
    else if(in_fifo_rdreq)
    begin
        wr_done <= #U_DLY 1'b0;
    end
    else if(fifo_wrreq)
    begin
        wr_done   <= #U_DLY (wr_data_cnt==2'd3);
    end 
end

always@(posedge clk,posedge rst)
begin
    if(rst==1'b1)
    begin
        fifo_wrdata <= 'h0;
    end
    else
    begin
        case(wr_data_cnt)
            2'd0:   fifo_wrdata   <= #U_DLY in_fifo_data0;
            2'd1:   fifo_wrdata   <= #U_DLY in_fifo_data1;
            2'd2:   fifo_wrdata   <= #U_DLY in_fifo_data2;
            2'd3:   fifo_wrdata   <= #U_DLY in_fifo_data3;
        endcase
    end
end

// instance
SCFIFO_128x8_FWFT u0(
  .clk          (clk),
  .rst          (rst),
  .din          (fifo_wrdata),
  .wr_en        (fifo_wrreq),
  .rd_en        (out_fifo_rdreq),
  .dout         (out_fifo_data),
  .full         (),
  .almost_full  (fifo_alfull),
  .empty        (out_fifo_empty),
  .almost_empty (out_fifo_alempty)
);

endmodule
